package org.java.vm;

import java.io.*;

/**
 * @author chenyang
 */
public class Parser {

    private BufferedReader reader;
    private String statement;
    private CommandType commandType;
    private String arg1;
    private String arg2;

    public Parser(File vmFile) {
        try {
            reader = new BufferedReader(new FileReader(vmFile));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public boolean hasMoreCommand() throws IOException {
        String line;
        while ((line = reader.readLine()) != null) {
            String trimLine = line.trim();
            if (!trimLine.isBlank() && !trimLine.startsWith("//")) {
                this.statement = trimLine;
                return true;
            }
        }
        return false;
    }


    public void advance() {
        reset();
        String[] args = this.statement.split(" ");
        if (args.length >= 3) {
            if (args[2].contains("//")) {
                args[2] = args[2].substring(0, args[2].indexOf("//"));
            }
            this.arg2 = args[2].trim();
        }
        if (args.length >= 2) {
            this.arg1 = args[1];
        }
        if (this.statement.startsWith("push")) {
            this.commandType = CommandType.C_PUSH;
        } else if (this.statement.startsWith("pop")) {
            // L命令
            this.commandType = CommandType.C_POP;
        } else if (this.statement.startsWith("label")) {
            this.commandType = CommandType.C_LABEL;
        } else if (this.statement.startsWith("if-goto")) {
            this.commandType = CommandType.C_IF;
        } else if (this.statement.startsWith("goto")) {
            this.commandType = CommandType.C_GOTO;
        } else if (this.statement.startsWith("function")) {
            this.commandType = CommandType.C_FUNCTION;
        } else if (this.statement.startsWith("return")) {
            this.commandType = CommandType.C_RETURN;
        } else if (this.statement.startsWith("call")) {
            this.commandType = CommandType.C_CALL;
        } else {
            this.arg1 = args[0].trim();
            this.commandType = CommandType.C_ARITHMETIC;
        }
    }

    private void reset() {
        this.commandType = null;
        this.arg1 = null;
        this.arg2 = null;
    }

    public CommandType commandType() {
        return commandType;
    }

    public String arg1() {
        return arg1;
    }

    public int arg2() {
        if (commandType == CommandType.C_PUSH || commandType == CommandType.C_POP
                || commandType == CommandType.C_CALL
                || commandType == CommandType.C_FUNCTION) {
            return Integer.parseInt(arg2);
        } else {
            return -1;
        }
    }
}
